﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Bierdopje.API
{
    /// <summary>
    /// Class to help with subtitle specific stuff
    /// </summary>
    public class SubHelper
    {
        private const string cVersionRegex = @"[\.]srt(?<Version>[\._][Vv]\d{1,2})|(?<Version>[\._][vV]\d{1,2})[\._]|-[^a-z]+?(?<Version>[\._]{0,1}V\d{1,2})[\.]srt";
        private const string cGetShowName = @"(?<ShowName>[\w\.]*)\.[Ss]";
        private const string cScenFileInfo = @"(?<ShowName>[\w\.-]*)\.[Ss](?<Season>\d{1,3})[Ee](?<Episode>\d{1,3})(?<SecEp>[Ee]\d{1,2}){0,1}\.(?<EpTag>[\w\.-[\d\s]]*\.){0,1}(?<Quality>(?:[Dd][Vv][Dd][Rr][Ii][Pp])|(?:[Ww][Ss]\.[Dd][Vv][Dd][Rr][Ii][Pp])|(?:[Hh][dD][tT][vV])|(?:720[pP]\.[hH][dD][tT][vV])|(?:720[pP]\.[bB][lL][uU][Rr][aA][yY])|(?:\w{0,3}\.[pP][dD][tT][vV])|(?:\w{0,2}\.\w{0,3}\.[pP][dD][tT][vV]))(?<MediaTypeIncDot>\.(?<MediaType>[\w]{0,4})){0,1}(?<RelGroupIncDot>-(?<RelGroup>.*)){0,1}(?<Extension>\.[\D]{3}){1}";
        private const string cEpisodeInfo = @"[Ss](?<Season>\d{1,2})[Ee](?<Episode>\d{1,2})";

        private static Regex sRegExFileInfo = new Regex(cScenFileInfo, RegexOptions.Compiled);
        private static Regex sRegExShowName = new Regex(cGetShowName, RegexOptions.Compiled);
        private static Regex sRegExEpisode = new Regex(cEpisodeInfo, RegexOptions.Compiled);

        public static EpisodeString GetEpInfoFromSEString(string SEString)
        {
            Match _Match = sRegExEpisode.Match(SEString);

            EpisodeString _EPS = new EpisodeString();
            _EPS.Episode = Convert.ToInt32(_Match.Groups["Episode"].Value);
            _EPS.Season = Convert.ToInt32(_Match.Groups["Season"].Value);
            return _EPS;
        }

        public class EpisodeString
        {
            private int m_Season;

            public int Season
            {
                get { return m_Season; }
                set { m_Season = value; }
            }
            private int m_Episode;

            public int Episode
            {
                get { return m_Episode; }
                set { m_Episode = value; }
            }
        }

        public class SceneInfo
        {
            private string m_ReleaseGroup;

            public string ReleaseGroup
            {
                get { return m_ReleaseGroup; }
                set { m_ReleaseGroup = value; }
            }
            private string m_EpisodeTag;

            public string EpisodeTag
            {
                get { return m_EpisodeTag; }
                set { m_EpisodeTag = value; }
            }

            private string m_ShowName;

            public string ShowName
            {
                get { return m_ShowName; }
                set { m_ShowName = value; }
            }
            private int m_Season;

            public int Season
            {
                get { return m_Season; }
                set { m_Season = value; }
            }
            private int m_Episode;

            public int Episode
            {
                get { return m_Episode; }
                set { m_Episode = value; }
            }
            private string m_Quality;

            public string Quality
            {
                get { return m_Quality; }
                set { m_Quality = value; }
            }
            private string m_MediaType;

            public string MediaType
            {
                get { return m_MediaType; }
                set { m_MediaType = value; }
            }
            private string m_Extension;

            public string Extension
            {
                get { return m_Extension; }
                set { m_Extension = value; }
            }

            public string SEString
            {
                get { return GenerateSEstring(this.Season, this.Episode); }
            }

            public override bool Equals(object obj)
            {
                if (obj.GetType() == typeof(SceneInfo))
                {
                    SceneInfo objToCompare = (SceneInfo)obj;

                    return (
                            (objToCompare.ShowName == this.ShowName)
                            &&
                            (objToCompare.SEString == this.SEString)
                            &&
                            (objToCompare.Season == this.Season)
                            &&
                            (objToCompare.ReleaseGroup == this.ReleaseGroup)
                            &&
                            (objToCompare.Quality == this.Quality)
                            &&
                            (objToCompare.MediaType == this.MediaType)
                            &&
                            (objToCompare.Extension == this.Extension)
                            &&
                            (objToCompare.EpisodeTag == this.EpisodeTag)
                            &&
                            (objToCompare.Episode == this.Episode)
                           );
                }
                else
                {
                    return base.Equals(obj);
                }
            }
        }

        /// <summary>
        /// Generates a string formated S01E02 style
        /// </summary>
        /// <param name="season">Season</param>
        /// <param name="episode">Episode</param>
        /// <returns>A well formed S??E?? string padded with zero's</returns>
        public static string GenerateSEstring(int season, int episode)
        {
            return string.Format("S{0}E{1}", TextHelper.PadIntWithZero(season, 2), TextHelper.PadIntWithZero(episode, 2));
        }

        /// <summary>
        /// Gets the scene ifo from the filename
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static SceneInfo GetInfoFromFileName(string fileName)
        {
            MatchCollection _Matches = sRegExFileInfo.Matches(RemoveVersionFromSubtitleFileName(fileName));

            SceneInfo _SC = new SceneInfo();

            foreach (Match _Match in _Matches)
            {
                _SC.ShowName = TextHelper.CapitalizeFirstLetter(_Match.Groups["ShowName"].Value.Replace('.', ' '));
                _SC.Episode = Convert.ToInt32(_Match.Groups["Episode"].Value);
                _SC.Season = Convert.ToInt32(_Match.Groups["Season"].Value);
                _SC.Quality = _Match.Groups["Quality"].Value.Replace('.', ' ');
                _SC.MediaType = _Match.Groups["MediaType"].Value;
                _SC.Extension = _Match.Groups["Extension"].Value;
                _SC.ReleaseGroup = _Match.Groups["RelGroup"].Value.Replace('.', ' ').ToUpper();
                _SC.EpisodeTag = TextHelper.CapitalizeFirstLetter(_Match.Groups["EpTag"].Value.Replace('.', ' '));
                return _SC;
            }

            return null;
        }

        public static string GetShowNameFromFileName(string fileName)
        {
            MatchCollection _Matches = sRegExShowName.Matches(fileName);

            foreach (Match _Match in _Matches)
            {
                return TextHelper.CapitalizeFirstLetter(_Match.Groups["ShowName"].Value.Replace('.', ' ')); ;
            }

            return "";
        }

        public static int GetSeasonFromFileName(string fileName)
        {
            MatchCollection _Matches = sRegExEpisode.Matches(fileName);

            foreach (Match _Match in _Matches)
            {
                return Convert.ToInt32(_Match.Groups["Season"].Value);
            }

            return -1;
        }

        public static int GetEpisodeFromFileName(string fileName)
        {
            MatchCollection _Matches = sRegExEpisode.Matches(fileName);

            foreach (Match _Match in _Matches)
            {
                return Convert.ToInt32(_Match.Groups["Episode"].Value);
            }

            return -1;
        }

        /// <summary>
        /// Remove version information from the subtitle 
        /// 
        /// Result:
        /// 
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.srt
        /// 
        /// These get removed:
        /// 
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION_V2.srt
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.V2.srt
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.srt.V1
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.srt.V12
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.srt_v1
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.V12.srt
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.v1.srt
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSIONV2.srt
        /// 
        /// These do not:
        /// 
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.V211.srt
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.srtV2
        /// Lie.to.Me.S01E13.720p.HDTV1.X264-DIMENSION.srt
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.srt.c1
        /// Lie.to.Me.S01E13.720p.HDTV.X264-DIMENSION.c123.srt
        /// 
        /// </summary>
        /// <param name="fileName">Filename to remove the version for</param>
        /// <returns>Clean filename</returns>
        public static string RemoveVersionFromSubtitleFileName(string fileName)
        {
            Regex _Regex = new Regex(cVersionRegex, RegexOptions.Compiled);
            return _Regex.Replace(fileName, new MatchEvaluator(RegexReplacer));
        }

        private static string RegexReplacer(Match m)
        {
            return m.Captures[0].Value.Replace(m.Groups["Version"].Value, "");
        }

 
    }
}
